/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package sismol.simulador;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Calendar;
import sismol.cartography.Linha;
import sismol.cartography.Ponto;
import sismol.cartography.Trecho;
import sismol.cartography.TrechoAtual;
import sismol.data.GerenciadorFactory;


/**
 *
 * @author koji
 */
public class Embarcado {
    
    private static final String URL = "http://186.204.38.174:8080/sismol/Embarcado.action";

    private Long onibusId;
    private Linha linha;
    private Trecho trecho;
    private Long distanciaPercorrida;
    private Long time;

    public Embarcado(Long onibusId, Linha linha) {
        this.onibusId = onibusId;
        this.linha = linha;
        this.time = Calendar.getInstance().getTimeInMillis();

        TrechoAtual trechoAtual = GerenciadorFactory.getGerenciadorEstimativa().buscaTrechoAtualPorOnibusId(onibusId);
        Trecho trecho0 = trechoAtual.getTrecho();
        this.trecho = (trecho0 != null) ? trecho0 : linha.getTrechos().get(0);
        Long distancia = trechoAtual.getDistanciaPercorrida();
        this.distanciaPercorrida = (distancia != null) ? distancia : 0;
    }

    public void step() {
        this.time = this.time + 10000;
        Double lat = 0d;
        Double lng = 0d;
        Long distancia;
        Double velocidade;

        Long distanciaTotal = trecho.getDistancia();
        // Simulador vai andar o ônibus alguns metros por vez.
        double hash = trecho.hashCode();
        double med = hash % 10 + 10;
        velocidade = (Math.sqrt(-2*Math.log(Math.random()) )*Math.cos( 2*Math.PI*Math.random())) + med;
        
        //Long andou = Math.round(100*i) + 100;
        System.out.println("Velocidade: " + velocidade);
        Long andou = velocidade.longValue() * 10;
        distancia = this.distanciaPercorrida + andou;
        boolean chegou = false;
        if (distancia > distanciaTotal) {
            chegou = true;
            distancia = distanciaTotal;
            andou = trecho.getDistancia() - this.distanciaPercorrida;
            lat = trecho.getPontoB().getLatitude();
            lng = trecho.getPontoB().getLongitude();
        } else {
            Ponto pontoA = trecho.getPontoA();
            Double latA = pontoA.getLatitude();
            Double lngA = pontoA.getLongitude();
            Ponto pontoB = trecho.getPontoB();
            Double latB = pontoB.getLatitude();
            Double lngB = pontoB.getLongitude();
            Double frac = distancia.doubleValue() / distanciaTotal.doubleValue();

            Double deltaLat = Math.abs((latA - latB)*frac);
            Double deltaLng = Math.abs((lngA - lngB)*frac);

            if (latA > latB) {
                lat = latA - deltaLat;
            } else {
                lat = latA + deltaLat;
            }
            if (lngA > lngB) {
                lng = lngA - deltaLng;
            } else {
                lng = lngA + deltaLng;
            }
        }
        this.distanciaPercorrida = distancia;

        this.sendPostRequest(lat, lng, distancia, velocidade, time);

        if(chegou) {
            this.distanciaPercorrida = 0L;
            int index = (this.linha.getTrechos().indexOf(this.trecho) + 1) % this.linha.getTrechos().size();
            this.setTrecho(this.linha.getTrechos().get(index));
        }
    }

    private void sendPostRequest(Double lat, Double lng, Long distancia, Double velocidade, Long time) {

        //Build parameter string
        String data = "id=" + this.onibusId + "&lat=" + lat + "&lng=" + lng + "&d=" + distancia + "&v=" +
                velocidade + "&h=" + time;
        System.out.println("Dados enviados: " + data);
        try {

            // Send the request
            URL url = new URL(URL);
            URLConnection conn = url.openConnection();
            conn.setDoOutput(true);
            OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());

            //write parameters
            writer.write(data);
            writer.flush();

            // Get the response
            BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String s = reader.readLine();
            StringBuilder sb = new StringBuilder();
            while (s != null) {
                sb.append(s);
                s = reader.readLine();
            }
            writer.close();
            reader.close();


        } catch (MalformedURLException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public Long getOnibusId() {
        return onibusId;
    }

    public void setOnibusId(Long onibusId) {
        this.onibusId = onibusId;
    }

    public Long getDistanciaPercorrida() {
        return distanciaPercorrida;
    }

    public void setDistanciaPercorrida(Long distanciaPercorrida) {
        this.distanciaPercorrida = distanciaPercorrida;
    }

    public Trecho getTrecho() {
        return trecho;
    }

    public void setTrecho(Trecho trecho) {
        this.trecho = trecho;
    }

    public Linha getLinha() {
        return linha;
    }

    public void setLinha(Linha linha) {
        this.linha = linha;
    }
}
